/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "vault_of_archavon.h"
#include "SpellAuras.h"
#include "SpellScript.h"

enum Events
{
    // Koralon
    EVENT_BURNING_BREATH			= 1,
    EVENT_FLAME_CINDER				= 2,
    EVENT_METEOR_FISTS				= 3,
};

enum Spells
{
    SPELL_BURNING_FURY                          = 68168,
    SPELL_BURNING_BREATH						= 66665, // handled by spell_difficulty
    
    SPELL_FLAMING_CINDER                        = 66681,
	SPELL_FLAMING_CINDER_DUMMY					= 66690,
	SPELL_FLAMING_CINDER_MISSILE				= 66682, // trigger of missile handled by spell_difficulty

    SPELL_METEOR_FISTS                          = 66725, // handled by spell_difficulty
    SPELL_METEOR_FISTS_DAMAGE                   = 66765,
    SPELL_FW_METEOR_FISTS_DAMAGE                = 66809
};

class boss_koralon : public CreatureScript
{
    public:
        boss_koralon() : CreatureScript("boss_koralon") { }

        struct boss_koralonAI : public ScriptedAI
        {
            boss_koralonAI(Creature* creature) : ScriptedAI(creature)
            {
				pInstance = me->GetInstanceScript();
            }

			InstanceScript* pInstance;
			EventMap events;
			uint32 rotateTimer;

			void Reset()
			{
				rotateTimer = 0;
				events.Reset();
				if (pInstance)
				{
					if (pInstance->GetData(DATA_STONED))
					{
						if (Aura* aur = me->AddAura(SPELL_STONED_AURA, me))
						{
							aur->SetMaxDuration(60 * MINUTE* IN_MILLISECONDS);
							aur->SetDuration(60 * MINUTE* IN_MILLISECONDS);
						}
					}
					pInstance->SetData(EVENT_KORALON, NOT_STARTED);
				}
			}

			void AttackStart(Unit* who)
			{
				if (me->HasAura(SPELL_STONED_AURA))
					return;

				ScriptedAI::AttackStart(who);
			}

            void EnterCombat(Unit* /*who*/)
            {
                me->CastSpell(me, SPELL_BURNING_FURY, true);

                events.ScheduleEvent(EVENT_BURNING_BREATH, 10000);
                events.ScheduleEvent(EVENT_METEOR_FISTS, 30000);
                events.ScheduleEvent(EVENT_FLAME_CINDER, 20000);

                if (pInstance)
					pInstance->SetData(EVENT_KORALON, IN_PROGRESS);
            }

			void JustDied(Unit* )
			{
				if (pInstance)
					pInstance->SetData(EVENT_KORALON, DONE);
			}

            void UpdateAI(uint32 diff)
            {
				if (rotateTimer)
				{
					rotateTimer += diff;
					if (rotateTimer >= 3000)
					{
						if (!me->HasUnitMovementFlag(MOVEMENTFLAG_LEFT))
						{
							me->SetUnitMovementFlags(MOVEMENTFLAG_LEFT);
							me->SendMovementFlagUpdate();
							rotateTimer = 1;
							return;
						}
						else
						{
							me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEFT);
							me->SendMovementFlagUpdate();
							rotateTimer = 0;
							return;
						}
					}
				}

                if (!UpdateVictim())
                    return;

                events.Update(diff);
                if (me->HasUnitState(UNIT_STATE_CASTING))
                    return;

                switch (events.GetEvent())
                {
                    case EVENT_BURNING_BREATH:
						rotateTimer = 1500;
                        me->CastSpell(me, SPELL_BURNING_BREATH, false);
                        events.RepeatEvent(45000);
                        break;
                    case EVENT_METEOR_FISTS:
                        me->CastSpell(me, SPELL_METEOR_FISTS, true);
                        events.RepeatEvent(45000);
                        break;
                    case EVENT_FLAME_CINDER:
                        me->CastSpell(me, SPELL_FLAMING_CINDER, true);
                        events.RepeatEvent(30000);
                        break;
                    default:
                        break;
                }

                DoMeleeAttackIfReady();
            }
        };

        CreatureAI* GetAI(Creature* creature) const
        {
            return new boss_koralonAI(creature);
        }
};

class spell_voa_flaming_cinder : public SpellScriptLoader
{
    public:
        spell_voa_flaming_cinder() : SpellScriptLoader("spell_voa_flaming_cinder") { }

        class spell_voa_flaming_cinder_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_voa_flaming_cinder_SpellScript);

            void HandleDummy(SpellEffIndex /*effIndex*/)
            {
				if (Unit* target = GetHitUnit())
					GetCaster()->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SPELL_FLAMING_CINDER_MISSILE, true);
            }

            void Register()
            {
                OnEffectHitTarget += SpellEffectFn(spell_voa_flaming_cinder_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_voa_flaming_cinder_SpellScript();
        }
};

class spell_koralon_meteor_fists : public SpellScriptLoader
{
    public:
        spell_koralon_meteor_fists() : SpellScriptLoader("spell_koralon_meteor_fists") { }

        class spell_koralon_meteor_fists_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_koralon_meteor_fists_AuraScript);

            bool Validate(SpellInfo const* /*spellInfo*/)
            {
                if (!sSpellMgr->GetSpellInfo(SPELL_METEOR_FISTS_DAMAGE))
                    return false;
                return true;
            }

            void TriggerFists(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
            {
                PreventDefaultAction();
                GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_METEOR_FISTS_DAMAGE, true, NULL, aurEff);
            }

            void Register()
            {
                OnEffectProc += AuraEffectProcFn(spell_koralon_meteor_fists_AuraScript::TriggerFists, EFFECT_0, SPELL_AURA_DUMMY);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_koralon_meteor_fists_AuraScript();
        }
};

class spell_flame_warder_meteor_fists : public SpellScriptLoader
{
    public:
        spell_flame_warder_meteor_fists() : SpellScriptLoader("spell_flame_warder_meteor_fists") { }

        class spell_flame_warder_meteor_fists_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_flame_warder_meteor_fists_AuraScript);

            bool Validate(SpellInfo const* /*spellInfo*/)
            {
                if (!sSpellMgr->GetSpellInfo(SPELL_FW_METEOR_FISTS_DAMAGE))
                    return false;
                return true;
            }

            void TriggerFists(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
            {
                PreventDefaultAction();
                GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_FW_METEOR_FISTS_DAMAGE, true, NULL, aurEff);
            }

            void Register()
            {
                OnEffectProc += AuraEffectProcFn(spell_flame_warder_meteor_fists_AuraScript::TriggerFists, EFFECT_0, SPELL_AURA_DUMMY);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_flame_warder_meteor_fists_AuraScript();
        }
};

void AddSC_boss_koralon()
{
    new boss_koralon();
	new spell_voa_flaming_cinder();
	new spell_koralon_meteor_fists();
	new spell_flame_warder_meteor_fists();
}
